import Watcher from "./observer/watcher";
import { patch } from "./vdom/patch";

export function lifecycleMixin(Vue) {
  Vue.prototype._update = function (vnode) {
    const vm = this;
    // 虚拟节点diff
    const preVnode = vm._vnode;  //保存上一次的虚拟节点，为了下次实现diff
    vm._vnode = vnode; // 给vm上加一个_vnode属性，再次更新是就能获取到该属性
    if(!preVnode){ //当不存在_vnode属性时，说明是第一个创建
      vm.$el = patch(vm.$el, vnode);
    } else {
      vm.$el = patch(preVnode, vnode);
    }

    // vnode即render函数的返回值,也就是createElement和createTextNode返回值
    // console.log("update", vnode);
    // 获取到虚拟节点vnode后，通过虚拟dom渲染出真实dom
    // 放到diff 判断的逻辑执行  
    // vm.$el = patch(vm.$el, vnode); // 用虚拟dom创建出的真实dom替换掉原el元素
  };
}

export function mountComponent(vm, el) {
  const options = vm.$options;
  vm.$el = el;

  // Watcher用来渲染页面
  // vm._render 通过解析render方法 渲染出虚拟dom
  // vm._update 通过虚拟dom创建出真实dom，并更新

  // callHook调用生命周期，beforeMount可以获取到el，但是是解析之前的
  callHook(vm, "beforeMount");
  // 渲染页面
  let updateComponent = () => {
    // console.log("update");
    // vm._render() 返回的虚拟dom
    // vm._update() 进行更新
    vm._update(vm._render()); // 先执行内部render，再执行update
  };

  // 每个组件都有一个watcher
  new Watcher(vm, updateComponent, () => {}, true); //最后true表示是渲染watcher
  // mounted可以获取到解析后的el
  callHook(vm, "mounted");
}

export function callHook(vm, hook) {
  const handlers = vm.$options[hook];
  if (handlers) {
    for (let i = 0; i < handlers.length; i++) {
      handlers[i].call(vm);
    }
  }
}
